#ifndef __MQ_HOST_
#define __MQ_HOST_
#include "mq_queue.hpp"
#include "mq_exchange.hpp"
#include "mq_message.hpp"
#include "mq_binding.hpp"

namespace MQ
{
    class VirtualHost
    {
    public:
        using ptr = std::shared_ptr<VirtualHost>;

        VirtualHost(const std::string &vhname, const std::string &basedir, const std::string &dbfile)
            : _vhname(vhname),
              _qmp(std::make_shared<QueueManager>(dbfile)),
              _emp(std::make_shared<ExchangeManager>(dbfile)),
              _bmp(std::make_shared<BindingManager>(dbfile)),
              _mmp(std::make_shared<MessageManager>(basedir))
        {
            QueueMap qm = _qmp->allQueue();
            for (auto &q : qm)
                _mmp->InitQueueMessage(q.first);
        }

        bool declareExchange(const std::string &ename, MQ::ExchangeType type, bool durable, bool auto_delete, const google::protobuf::Map<std::string, std::string> &args)
        {
            return _emp->declareExchange(ename, type, durable, auto_delete, args);
        }

        void deleteExchange(const std::string &ename)
        {
            _emp->deleteExchange(ename);
            _bmp->deleteExchangebinding(ename);
        }

        bool declareQueue(const std::string &qname, bool durable, bool exclusive, bool auto_delete, const google::protobuf::Map<std::string, std::string> &args)
        {
            _mmp->InitQueueMessage(qname);
            return _qmp->declareQueue(qname, durable, exclusive, auto_delete, args);
        }

        void deleteQueue(const std::string &qname)
        {
            _mmp->DestoryQueueMessage(qname);
            _bmp->deleteQueuebinding(qname);
            _qmp->deleteQueue(qname);
        }

        bool bind(const std::string &ename, const std::string &qname, const std::string &key)
        {
            bool it1 = _emp->exists(ename);
            bool it2 = _qmp->exists(qname);
            if ((it1 && it2) == false)
            {
                LOG(ERROR, "不存在该队列/交换机!!!\n");
                return false;
            }
            Exchange::ptr ep = _emp->selectExchange(ename);
            MsgQueue::ptr qp = _qmp->selectQueue(qname);
            return _bmp->bind(ename, qname, key, ep->durable && qp->durable);
        }

        void unbind(const std::string &ename, const std::string &qname)
        {
            _bmp->unbind(ename, qname);
        }

        bool basicPublish(const std::string &qname, MQ::BasicProperties *basic, const std::string &body)
        {
            MsgQueue::ptr mp = _qmp->selectQueue(qname);
            return _mmp->insert(qname, basic, body, mp->durable);
        }

        MessagePtr basicConsume(const std::string &qname)
        {
            return _mmp->front(qname);
        }

        void basicAck(const std::string &qname, const std::string &msg_id)
        {
            return _mmp->ack(qname, msg_id);
        }

        void clear()
        {
            _qmp->clear();
            _emp->clear();
            _mmp->clear();
            _bmp->clear();
        }

        bool existsExchange(const std::string &ename)
        {
            return _emp->exists(ename);
        }

        bool existsBinding(const std::string &ename, const std::string &qname)
        {
            return _bmp->exists(ename, qname);
        }

        bool existsQueue(const std::string &qname)
        {
            return _qmp->exists(qname);
        }

        MsgQueueBindingMap getExchangeBinding(const std::string &ename)
        {
            return _bmp->getExchange(ename);
        }

        QueueMap allQueue()
        {
            return _qmp->allQueue();
        }

        Exchange::ptr selectExchange(const std::string &ename)
        {
            return _emp->selectExchange(ename);
        }

        MsgQueue::ptr selectQueue(const std::string &qname)
        {
            return _qmp->selectQueue(qname);
        }

    private:
        std::string _vhname;
        QueueManager::ptr _qmp;       // 队列管理句柄
        ExchangeManager::ptr _emp;    // 交换机管理句柄
        BindingManager::ptr _bmp;     // 绑定管理句柄
        MQ::MessageManager::ptr _mmp; // 消息管理句柄
    };
}

#endif